﻿#if NETFX

using Apewer;
using Apewer.Internals;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Text;
using System.Web;
using System.Web.Configuration;

namespace Apewer.Web
{

    /// <summary>实现页面的常用功能。</summary>
    public class PageUtility // : System.Web.UI.Page
    {

        #region Property

        /// <summary>获取客户端 IP 地址。</summary>
        public static string ClientIP
        {
            get
            {
                var ip1 = Variable("http_x_forwarded_for");
                var ip2 = Variable("remote_addr");
                var e1 = string.IsNullOrEmpty(ip1);
                var e2 = string.IsNullOrEmpty(ip2);
                var result = TextUtility.Empty;
                if (e1)
                {
                    if (e2) result = TextUtility.Empty;
                    else result = TextUtility.Merge(ip2);
                }
                else
                {
                    if (e2) result = TextUtility.Merge(ip1);
                    else result = TextUtility.Merge(ip1, ",", ip2);
                }
                return result;
            }
        }

        /// <summary>检查客户端是否在线。</summary>
        public static bool Connected
        {
            get
            {
                try { return HttpContext.Current.Response.IsClientConnected; }
                catch { return false; }
            }
        }

        /// <summary>获取服务器执行的文件 URL。</summary>
        public static string ExecutingUrl
        {
            get
            {
                return Variable("url");
            }
        }

        /// <summary>获取上一次的 URL。</summary>
        public static string PreviousUrl
        {
            get
            {
                return Variable("http_referer");
            }
        }

        /// <summary>获取客户端请求的 URL。</summary>
        public static string RequestingUrl
        {
            get
            {
                try { return HttpContext.Current.Request.Url.OriginalString; }
                catch { return TextUtility.Empty; }
            }
        }

        /// <summary>获取分段的 URL。</summary>
        public static string[] SegmentalUrl
        {
            get
            {
                try { return HttpContext.Current.Request.Url.AbsolutePath.Split('/'); }
                catch { return new string[0]; }
            }
        }

        /// <summary>获取浏览器用户代理。</summary>
        public static string UserAgent
        {
            get
            {
                return Variable("http_user_agent");
            }
        }

        /// <summary>获取服务器变量。</summary>
        public static Dictionary<string, string> Variables
        {
            get
            {
                var collection = HttpContext.Current.Request.ServerVariables;
                var dictionary = new Dictionary<string, string>();
                foreach (var key in collection.AllKeys)
                {
                    if (dictionary.ContainsKey(key)) continue;
                    dictionary.Add(key, collection[key] ?? "");
                }
                return dictionary;
            }
        }

        #endregion

        #region server / web.config

        /// <summary>获取访问 web.config 文件中 configuration.appSettings 子项的集合。</summary>
        public static NameValueCollection AppSettings { get { return WebConfigurationManager.AppSettings; } }

        /// <summary>获取从 web.config 文件中 configuration.appSettings 的子项。</summary>
        public static Dictionary<string, string> GetAppSettings()
        {
            var ts = new TextSet(true);
            try
            {
                var appsettings = WebConfigurationManager.AppSettings;
                foreach (var key in appsettings.AllKeys)
                {
                    var value = appsettings[key];
                    ts[key] = value;
                }
            }
            catch { }
            return ts.Origin();
        }

        /// <summary>获取从 web.config 文件中 configuration.appSettings 的子项。</summary>
        public static string GetAppSettings(string key)
        {
            if (key != null)
            {
                try
                {
                    var appsettings = WebConfigurationManager.AppSettings;
                    var value = appsettings[key];
                    return TextUtility.Trim(value);
                }
                catch { }
            }
            return "";
        }

        /// <summary>设置 web.config 文件中 configuration.appSettings 的子项。</summary>
        public static bool SetAppSettings(string key, string value)
        {
            try
            {
                WebConfigurationManager.AppSettings.Set(key ?? "", value ?? "");
                return true;
            }
            catch { return false; }
        }

        /// <summary>获取服务器变量。</summary>
        public static string Variable(string name)
        {
            var result = "";
            if (!string.IsNullOrEmpty(name))
            {
                string vname = name.ToLower();
                try { result = HttpContext.Current.Request.ServerVariables[vname]; }
                finally { }
            }
            return result ?? "";
        }

        /// <summary>执行 ASPX 文件，执行完毕后返回原程序继续执行。</summary>
        public static bool Execute(string url)
        {
            try { HttpContext.Current.Server.Execute(url); return true; }
            catch { return false; }
        }

        /// <summary>执行 ASPX 文件，不再返回。</summary>
        public static bool Transfer(string url)
        {
            try { HttpContext.Current.Server.Transfer(url); return true; }
            catch { return false; }
        }

        #endregion

        #region cookie / session

        /// <summary>获取 Cookie 值。</summary>
        public static string GetCookie(string name)
        {
            if (!string.IsNullOrEmpty(name))
            {
                try
                {
                    return HttpContext.Current.Request.Cookies[name].Value;
                }
                finally { }
            }
            return "";
        }

        /// <summary>清除所有 Cookie。</summary>
        public static void ClearCookie()
        {
            try
            {
                HttpContext.Current.Response.Cookies.Clear();
            }
            finally { }
        }

        /// <summary>获取会话变量值。</summary>
        public static string GetSession(string name)
        {
            if (!string.IsNullOrEmpty(name))
            {
                try
                {
                    object session = HttpContext.Current.Session[name];
                    if (session != null) return session.ToString();
                }
                finally { }
            }
            return "";
        }

        #endregion

        #region request

        /// <summary>获取 POST 提交的数据。</summary>
        public static byte[] GetPost()
        {
            try
            {
                var length = HttpContext.Current.Request.InputStream.Length;
                if (length > 0)
                {
                    var data = new byte[(int)length];
                    HttpContext.Current.Request.InputStream.Read(data, 0, (int)length);
                    return data;
                }
            }
            finally { }
            return BytesUtility.Empty;
        }

        /// <summary>获取物理路径。</summary>
        public static string MapPath(string url)
        {
            try
            {
                return HttpContext.Current.Server.MapPath(url);
            }
            catch { return ""; }
        }

        /// <summary>获取 GET 提交的值。</summary>
        public static string QueryString(string name, bool decode = false)
        {
            if (string.IsNullOrEmpty(name)) return "";
            try
            {
                var value = HttpContext.Current.Request.QueryString[name] ?? "";
                if (decode) value = HttpUtility.UrlDecode(value);
                return value;
            }
            catch { }
            return "";
        }

        /// <summary>重定向到新 URL。</summary>
        public static void Redirect(string url)
        {
            try
            {
                HttpContext.Current.Response.Redirect(string.IsNullOrEmpty(url) ? "/" : url);
            }
            catch { }
        }

        /// <summary>移除 Cookie。</summary>
        public static bool RemoveCookie(string name)
        {
            if (!string.IsNullOrEmpty(name))
            {
                try
                {
                    HttpContext.Current.Response.Cookies.Remove(name);
                    return true;
                }
                finally { }
            }
            return false;
        }

        /// <summary>获取 FORM 提交的文件。</summary>
        public static Dictionary<string, byte[]> RequestFile()
        {
            var result = new Dictionary<string, byte[]>();
            try
            {
                var context = HttpContext.Current;
                if (context == null) return result;
                foreach (var key in context.Request.Files.AllKeys)
                {
                    var file = context.Request.Files.Get(key);
                    var exist = result.ContainsKey(file.FileName);
                    if (exist) continue;

                    var memory = new System.IO.MemoryStream();
                    var read = BytesUtility.Read(file.InputStream, memory);
                    var data = memory.ToArray();
                    memory.Dispose();

                    if (data.Length == file.ContentLength)
                    {
                        result.Add(file.FileName, data);
                    }
                }
            }
            catch { }
            return result;
        }

        /// <summary>获取 POST 提交的值。</summary>
        public static string RequestForm(string name)
        {
            try
            {
                if (!string.IsNullOrEmpty(name)) return HttpContext.Current.Request.Form[name];
            }
            finally { }
            return "";
        }

        /// <summary>设置 Cookie 值。</summary>
        public static bool SetCookie(string name, string value)
        {
            if (!string.IsNullOrEmpty(name))
            {
                try
                {
                    HttpContext.Current.Response.Cookies[name].Value = value;
                    return true;
                }
                finally { }
            }
            return false;
        }

        /// <summary>设置 Cookie 过期时间。</summary>
        public static bool SetCookie(string name, DateTime expires)
        {
            if (!string.IsNullOrEmpty(name) && expires != null)
            {
                try
                {
                    HttpContext.Current.Response.Cookies[name].Expires = expires;
                    return true;
                }
                finally { }
            }
            return false;
        }

        /// <summary>设置会话变量值。</summary>
        public static bool SetSession(string name, string value)
        {
            if (!string.IsNullOrEmpty(name))
            {
                try
                {
                    if (string.IsNullOrEmpty(value))
                    {
                        HttpContext.Current.Session.Remove(value);
                    }
                    else
                    {
                        HttpContext.Current.Session[name] = value;
                    }
                    return true;
                }
                finally { }
            }
            return false;
        }

        #endregion

        #region response

        /// <summary>设置响应：启用输出缓冲，禁用缓存，设置字符集为“UTF-8”。</summary>
        public static void InitializeResponse()
        {
            try
            {
                HttpContext.Current.Response.Buffer = true;
                HttpContext.Current.Response.Expires = 0;
                HttpContext.Current.Response.Charset = "utf-8";
            }
            finally { }
        }

        /// <summary>清空缓冲区内容，默认不向客户端发送缓冲区内容。</summary>
        public void ClearResponse()
        {
            try { HttpContext.Current.Response.Clear(); } catch { }
        }

        /// <summary>清空缓冲区内容，可选是否向客户端发送缓冲区内容。</summary>
        public void ClearResponse(bool flush)
        {
            try { if (flush) HttpContext.Current.Response.Flush(); } catch { }
            try { HttpContext.Current.Response.Clear(); } catch { }
        }

        /// <summary>向客户端发送缓冲区内容，并结束页面的执行。</summary>
        public static void StopResponse()
        {
            try { HttpContext.Current.Response.Flush(); } finally { }
            try { HttpContext.Current.Response.Close(); } finally { }
        }

        /// <summary>停止并关闭响应流。可指定向发送缓冲区的数据。</summary>
        public static void StopResponse(bool flush)
        {
            try { if (flush) HttpContext.Current.Response.Flush(); } finally { }
            try { HttpContext.Current.Response.Close(); } finally { }
            // try { HttpContext.Current.Response.End(); } finally { }
        }

        /// <summary>向响应流写入文本。</summary>
        public static Exception Write(params string[] text)
        {
            if (text == null) return null;
            foreach (var i in text)
            {
                if (string.IsNullOrEmpty(i)) continue;
                try
                {
                    HttpContext.Current.Response.Write(i);
                }
                catch (Exception exception) { return exception; }
            }
            return null;
        }

        /// <summary>输出二进制。Content-Type 为“application/octet-stream”。</summary>
        public static Exception Write(byte[] bytes)
        {
            var ct = "application/octet-stream";
            var data = bytes ?? BytesUtility.Empty;
            try
            {
                HttpContext.Current.Response.ContentType = ct;
                HttpContext.Current.Response.OutputStream.Write(bytes, 0, bytes.Length);
                return null;
            }
            catch (Exception exception) { return exception; }
        }

        /// <summary>输出二进制。Content-Type 默认为“application/octet-stream”。</summary>
        public static Exception Write(byte[] bytes, string contentType)
        {
            var data = bytes ?? BytesUtility.Empty;
            var contenttype = TextUtility.IsBlank(contentType) ? "application/octet-stream" : contentType;
            try
            {
                HttpContext.Current.Response.ContentType = contenttype;
                if (data.LongLength > 0L) HttpContext.Current.Response.OutputStream.Write(data, 0, data.Length);
                return null;
            }
            catch (Exception exception) { return exception; }
        }

        /// <summary>输出文件。</summary>
        public static Exception WriteFile(string name, string path)
        {
            var vname = StorageUtility.FixFileName(name);
            try
            {
                HttpContext.Current.Response.ContentType = "application/octet-stream";
                if (!TextUtility.IsBlank(vname))
                {
                    HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment; filename=" + HttpUtility.UrlEncode(vname, Encoding.UTF8));
                }
                HttpContext.Current.Response.WriteFile(path, false);
                HttpContext.Current.Response.Flush();
                HttpContext.Current.Response.End();
                return null;
            }
            catch (Exception exception) { return exception; }
        }

        /// <summary>输出文件。Content-Type 值为“application/octet-stream”。</summary>
        public static Exception WriteFile(string name, params byte[] bytes)
        {
            var vname = StorageUtility.FixFileName(name);
            try
            {
                HttpContext.Current.Response.ContentType = "application/octet-stream";
                if (!TextUtility.IsBlank(vname))
                {
                    HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment; filename=" + HttpUtility.UrlEncode(vname, Encoding.UTF8));
                }
                HttpContext.Current.Response.OutputStream.Write(bytes, 0, bytes.Length);
                return null;
            }
            catch (Exception exception) { return exception; }
        }

        /// <summary>编码 URL。</summary>
        public static string UrlEncode(string text)
        {
            try { return HttpUtility.UrlEncode(text); }
            catch { return TextUtility.Empty; }
        }

        /// <summary>解码 URL。</summary>
        public static string UrlDecode(string text)
        {
            try { return HttpUtility.UrlDecode(text); }
            catch { return TextUtility.Empty; }
        }

        /// <summary></summary>
        public static string GetMime(string name)
        {
            var octetstream = "application/octet-stream";
            if (string.IsNullOrEmpty(name)) return octetstream;
            if (!name.Contains(".")) return octetstream;

            var array = name.ToLower().Split('.');
            var extension = array[array.Length - 1];

            var mime = null as string;
            if (string.IsNullOrEmpty(mime)) mime = GetMime_Nginx_1_16_1(extension);

            return string.IsNullOrEmpty(mime) ? octetstream : mime;
        }

        private static TextSet GetMime_Customized()
        {
            var ts = new TextSet(true);
            ts[""] = "application/octet-stream";

            // 纯文本文件。
            ts["htm"] = "text/html";
            ts["html"] = "text/html";
            ts["css"] = "text/css";
            ts["js"] = "application/x-javascript";
            ts["txt"] = "text/plain";
            ts["txt"] = "text/plain";

            // 字体文件。
            ts["eot"] = "application/vnd.ms-fontobject";
            ts["ttf"] = "application/x-font-ttf";
            ts["woff"] = "application/x-font-woff";

            // 图像文件。
            ts["bmp"] = "image/bmp";
            ts["gif"] = "image/gif";
            ts["ico"] = "imaeg/x-icon";
            ts["jpg"] = "image/jpg";
            ts["png"] = "image/png";
            ts["svg"] = "image/svg+xml";

            // 音视频文件。
            ts["avi"] = "video/avi";
            ts["mov"] = "video/mov";
            ts["mp3"] = "audio/mp3";
            ts["mp4"] = "video/mp4";
            ts["ogg"] = "video/ogg";
            ts["rm"] = "video/rm";
            ts["rmvb"] = "video/rmvb";
            ts["wav"] = "audio/wav";
            ts["webm"] = "video/webm";
            ts["wma"] = "video/wma";
            ts["wmv"] = "video/wmv";

            // 常用二进制文件。
            //ts["7z"] = "application/octet-stream";
            //ts["exe"] = "application/octet-stream";
            //ts["gz"] = "application/octet-stream";
            //ts["rar"] = "application/octet-stream";
            //ts["tar"] = "application/octet-stream";
            //ts["zip"] = "application/x-zip-compressed";

            return ts;
        }

        private static string GetMime_Nginx_1_16_1(string extension)
        {
            switch (extension)
            {
                case "3gp": return "video/3gpp";
                case "3gpp": return "video/3gpp";
                case "7z": return "application/x-7z-compressed";
                case "ai": return "application/postscript";
                case "asf": return "video/x-ms-asf";
                case "asx": return "video/x-ms-asf";
                case "atom": return "application/atom+xml";
                case "avi": return "video/x-msvideo";
                case "bin": return "application/octet-stream";
                case "bmp": return "image/x-ms-bmp";
                case "cco": return "application/x-cocoa";
                case "crt": return "application/x-x509-ca-cert";
                case "css": return "text/css";
                case "deb": return "application/octet-stream";
                case "der": return "application/x-x509-ca-cert";
                case "dll": return "application/octet-stream";
                case "dmg": return "application/octet-stream";
                case "doc": return "application/msword";
                case "docx": return "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
                case "ear": return "application/java-archive";
                case "eot": return "application/vnd.ms-fontobject";
                case "eps": return "application/postscript";
                case "exe": return "application/octet-stream";
                case "flv": return "video/x-flv";
                case "gif": return "image/gif";
                case "hqx": return "application/mac-binhex40";
                case "htc": return "text/x-component";
                case "htm": return "text/html";
                case "html": return "text/html";
                case "ico": return "image/x-icon";
                case "img": return "application/octet-stream";
                case "iso": return "application/octet-stream";
                case "jad": return "text/vnd.sun.j2me.app-descriptor";
                case "jar": return "application/java-archive";
                case "jardiff": return "application/x-java-archive-diff";
                case "jng": return "image/x-jng";
                case "jnlp": return "application/x-java-jnlp-file";
                case "jpeg": return "image/jpeg";
                case "jpg": return "image/jpeg";
                case "js": return "application/javascript";
                case "json": return "application/json";
                case "kar": return "audio/midi";
                case "kml": return "application/vnd.google-earth.kml+xml";
                case "kmz": return "application/vnd.google-earth.kmz";
                case "m3u8": return "application/vnd.apple.mpegurl";
                case "m4a": return "audio/x-m4a";
                case "m4v": return "video/x-m4v";
                case "mid": return "audio/midi";
                case "midi": return "audio/midi";
                case "mml": return "text/mathml";
                case "mng": return "video/x-mng";
                case "mov": return "video/quicktime";
                case "mp3": return "audio/mpeg";
                case "mp4": return "video/mp4";
                case "mpeg": return "video/mpeg";
                case "mpg": return "video/mpeg";
                case "msi": return "application/octet-stream";
                case "msm": return "application/octet-stream";
                case "msp": return "application/octet-stream";
                case "odg": return "application/vnd.oasis.opendocument.graphics";
                case "odp": return "application/vnd.oasis.opendocument.presentation";
                case "ods": return "application/vnd.oasis.opendocument.spreadsheet";
                case "odt": return "application/vnd.oasis.opendocument.text";
                case "ogg": return "audio/ogg";
                case "pdb": return "application/x-pilot";
                case "pdf": return "application/pdf";
                case "pem": return "application/x-x509-ca-cert";
                case "pl": return "application/x-perl";
                case "pm": return "application/x-perl";
                case "png": return "image/png";
                case "ppt": return "application/vnd.ms-powerpoint";
                case "pptx": return "application/vnd.openxmlformats-officedocument.presentationml.presentation";
                case "prc": return "application/x-pilot";
                case "ps": return "application/postscript";
                case "ra": return "audio/x-realaudio";
                case "rar": return "application/x-rar-compressed";
                case "rpm": return "application/x-redhat-package-manager";
                case "rss": return "application/rss+xml";
                case "rtf": return "application/rtf";
                case "run": return "application/x-makeself";
                case "sea": return "application/x-sea";
                case "shtml": return "text/html";
                case "sit": return "application/x-stuffit";
                case "svg": return "image/svg+xml";
                case "svgz": return "image/svg+xml";
                case "swf": return "application/x-shockwave-flash";
                case "tcl": return "application/x-tcl";
                case "tif": return "image/tiff";
                case "tiff": return "image/tiff";
                case "tk": return "application/x-tcl";
                case "ts": return "video/mp2t";
                case "txt": return "text/plain";
                case "war": return "application/java-archive";
                case "wbmp": return "image/vnd.wap.wbmp";
                case "webm": return "video/webm";
                case "webp": return "image/webp";
                case "wml": return "text/vnd.wap.wml";
                case "wmlc": return "application/vnd.wap.wmlc";
                case "wmv": return "video/x-ms-wmv";
                case "woff": return "font/woff";
                case "woff2": return "font/woff2";
                case "xhtml": return "application/xhtml+xml";
                case "xls": return "application/vnd.ms-excel";
                case "xlsx": return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
                case "xml": return "text/xml";
                case "xpi": return "application/x-xpinstall";
                case "xspf": return "application/xspf+xml";
                case "zip": return "application/zip";
            }
            return null;
        }

        #endregion

    }

}

#endif
